"""
表格组件
提供各种数据表格展示组件
"""

import streamlit as st
import pandas as pd
from typing import Dict, List, Any, Optional, Callable
from datetime import datetime
import numpy as np


def create_data_table(
    data: pd.DataFrame,
    title: Optional[str] = None,
    searchable: bool = True,
    sortable: bool = True,
    paginated: bool = True,
    page_size: int = 20,
    height: Optional[int] = None,
    column_config: Optional[Dict[str, Any]] = None
):
    """
    创建数据表格
    
    Args:
        data: 数据框
        title: 表格标题
        searchable: 是否可搜索
        sortable: 是否可排序
        paginated: 是否分页
        page_size: 每页大小
        height: 表格高度
        column_config: 列配置
    """
    if title:
        st.subheader(title)
    
    # 搜索功能
    if searchable and not data.empty:
        search_term = st.text_input("🔍 搜索", key=f"search_{id(data)}")
        if search_term:
            # 在所有文本列中搜索
            text_columns = data.select_dtypes(include=['object', 'string']).columns
            mask = pd.Series([False] * len(data))
            for col in text_columns:
                mask |= data[col].astype(str).str.contains(search_term, case=False, na=False)
            data = data[mask]
    
    # 分页功能
    if paginated and len(data) > page_size:
        total_pages = (len(data) - 1) // page_size + 1
        page = st.selectbox(
            f"页面 (共 {total_pages} 页)",
            range(1, total_pages + 1),
            key=f"page_{id(data)}"
        )
        start_idx = (page - 1) * page_size
        end_idx = start_idx + page_size
        data = data.iloc[start_idx:end_idx]
    
    # 显示表格
    st.dataframe(
        data,
        use_container_width=True,
        height=height,
        column_config=column_config
    )
    
    # 显示统计信息
    if not data.empty:
        col1, col2, col3 = st.columns(3)
        with col1:
            st.metric("总行数", len(data))
        with col2:
            st.metric("总列数", len(data.columns))
        with col3:
            st.metric("内存使用", f"{data.memory_usage(deep=True).sum() / 1024:.1f} KB")


def create_editable_table(
    data: pd.DataFrame,
    title: Optional[str] = None,
    key: str = "editable_table",
    on_change: Optional[Callable] = None
) -> pd.DataFrame:
    """
    创建可编辑表格
    
    Args:
        data: 数据框
        title: 表格标题
        key: 组件键
        on_change: 变化回调函数
    
    Returns:
        编辑后的数据框
    """
    if title:
        st.subheader(title)
    
    # 使用data_editor创建可编辑表格
    edited_data = st.data_editor(
        data,
        use_container_width=True,
        key=key,
        on_change=on_change,
        num_rows="dynamic"
    )
    
    return edited_data


def create_comparison_table(
    data_dict: Dict[str, pd.DataFrame],
    title: Optional[str] = None,
    comparison_column: str = "指标"
):
    """
    创建对比表格
    
    Args:
        data_dict: 数据字典 {名称: 数据框}
        title: 表格标题
        comparison_column: 对比列名
    """
    if title:
        st.subheader(title)
    
    # 合并数据
    combined_data = pd.DataFrame()
    
    for name, df in data_dict.items():
        if comparison_column in df.columns:
            temp_df = df.set_index(comparison_column)
            temp_df.columns = [f"{name}_{col}" for col in temp_df.columns]
            if combined_data.empty:
                combined_data = temp_df
            else:
                combined_data = combined_data.join(temp_df, how='outer')
    
    if not combined_data.empty:
        st.dataframe(combined_data, use_container_width=True)
    else:
        st.warning("没有可对比的数据")


def create_pivot_table(
    data: pd.DataFrame,
    title: Optional[str] = None,
    index_cols: Optional[List[str]] = None,
    column_cols: Optional[List[str]] = None,
    value_cols: Optional[List[str]] = None,
    aggfunc: str = "sum"
):
    """
    创建透视表
    
    Args:
        data: 数据框
        title: 表格标题
        index_cols: 索引列
        column_cols: 列字段
        value_cols: 值字段
        aggfunc: 聚合函数
    """
    if title:
        st.subheader(title)
    
    if data.empty:
        st.warning("没有数据可显示")
        return
    
    # 交互式选择字段
    col1, col2, col3 = st.columns(3)
    
    with col1:
        if index_cols is None:
            index_cols = st.multiselect(
                "选择行字段",
                data.columns.tolist(),
                key=f"pivot_index_{id(data)}"
            )
    
    with col2:
        if column_cols is None:
            column_cols = st.multiselect(
                "选择列字段",
                data.columns.tolist(),
                key=f"pivot_columns_{id(data)}"
            )
    
    with col3:
        if value_cols is None:
            numeric_cols = data.select_dtypes(include=[np.number]).columns.tolist()
            value_cols = st.multiselect(
                "选择值字段",
                numeric_cols,
                key=f"pivot_values_{id(data)}"
            )
    
    # 创建透视表
    if index_cols and value_cols:
        try:
            pivot_data = pd.pivot_table(
                data,
                index=index_cols,
                columns=column_cols if column_cols else None,
                values=value_cols,
                aggfunc=aggfunc,
                fill_value=0
            )
            
            st.dataframe(pivot_data, use_container_width=True)
            
            # 下载按钮
            csv = pivot_data.to_csv()
            st.download_button(
                label="下载透视表",
                data=csv,
                file_name=f"pivot_table_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
                mime="text/csv"
            )
            
        except Exception as e:
            st.error(f"创建透视表失败: {e}")
    else:
        st.info("请选择至少一个行字段和一个值字段")


def create_summary_table(
    data: pd.DataFrame,
    title: Optional[str] = None,
    group_by: Optional[str] = None
):
    """
    创建汇总表
    
    Args:
        data: 数据框
        title: 表格标题
        group_by: 分组字段
    """
    if title:
        st.subheader(title)
    
    if data.empty:
        st.warning("没有数据可显示")
        return
    
    # 数值列统计
    numeric_cols = data.select_dtypes(include=[np.number]).columns
    
    if len(numeric_cols) == 0:
        st.warning("没有数值列可统计")
        return
    
    if group_by and group_by in data.columns:
        # 分组统计
        summary = data.groupby(group_by)[numeric_cols].agg([
            'count', 'mean', 'std', 'min', 'max', 'sum'
        ]).round(2)
        
        # 展平多级列名
        summary.columns = [f"{col[0]}_{col[1]}" for col in summary.columns]
        summary = summary.reset_index()
        
    else:
        # 整体统计
        summary = data[numeric_cols].describe().T
        summary = summary.round(2)
        summary = summary.reset_index()
        summary.rename(columns={'index': '字段'}, inplace=True)
    
    st.dataframe(summary, use_container_width=True)


def create_correlation_table(
    data: pd.DataFrame,
    title: Optional[str] = None,
    method: str = "pearson"
):
    """
    创建相关性表格
    
    Args:
        data: 数据框
        title: 表格标题
        method: 相关性方法 (pearson, spearman, kendall)
    """
    if title:
        st.subheader(title)
    
    # 只选择数值列
    numeric_data = data.select_dtypes(include=[np.number])
    
    if numeric_data.empty:
        st.warning("没有数值列可计算相关性")
        return
    
    # 计算相关性
    corr_matrix = numeric_data.corr(method=method)
    
    # 显示相关性矩阵
    st.dataframe(
        corr_matrix.style.background_gradient(cmap='RdYlBu_r', center=0),
        use_container_width=True
    )
    
    # 显示强相关性对
    st.subheader("强相关性对 (|r| > 0.7)")
    strong_corr = []
    
    for i in range(len(corr_matrix.columns)):
        for j in range(i+1, len(corr_matrix.columns)):
            corr_val = corr_matrix.iloc[i, j]
            if abs(corr_val) > 0.7:
                strong_corr.append({
                    '变量1': corr_matrix.columns[i],
                    '变量2': corr_matrix.columns[j],
                    '相关系数': round(corr_val, 3)
                })
    
    if strong_corr:
        st.dataframe(pd.DataFrame(strong_corr), use_container_width=True)
    else:
        st.info("没有发现强相关性对")


def create_ranking_table(
    data: pd.DataFrame,
    rank_column: str,
    title: Optional[str] = None,
    ascending: bool = False,
    top_n: int = 10
):
    """
    创建排名表格
    
    Args:
        data: 数据框
        rank_column: 排名依据列
        title: 表格标题
        ascending: 是否升序
        top_n: 显示前N名
    """
    if title:
        st.subheader(title)
    
    if rank_column not in data.columns:
        st.error(f"列 '{rank_column}' 不存在")
        return
    
    # 排序并添加排名
    sorted_data = data.sort_values(rank_column, ascending=ascending).head(top_n)
    sorted_data = sorted_data.reset_index(drop=True)
    sorted_data.index = sorted_data.index + 1
    sorted_data.index.name = '排名'
    
    # 添加排名图标
    def add_rank_icon(rank):
        if rank == 1:
            return "🥇"
        elif rank == 2:
            return "🥈"
        elif rank == 3:
            return "🥉"
        else:
            return f"{rank}"
    
    sorted_data.insert(0, '排名图标', [add_rank_icon(i) for i in sorted_data.index])
    
    st.dataframe(sorted_data, use_container_width=True)


def create_financial_table(
    data: pd.DataFrame,
    title: Optional[str] = None,
    currency_columns: Optional[List[str]] = None,
    percentage_columns: Optional[List[str]] = None
):
    """
    创建金融数据表格
    
    Args:
        data: 数据框
        title: 表格标题
        currency_columns: 货币列
        percentage_columns: 百分比列
    """
    if title:
        st.subheader(title)
    
    # 格式化配置
    column_config = {}
    
    if currency_columns:
        for col in currency_columns:
            if col in data.columns:
                column_config[col] = st.column_config.NumberColumn(
                    col,
                    format="¥%.2f"
                )
    
    if percentage_columns:
        for col in percentage_columns:
            if col in data.columns:
                column_config[col] = st.column_config.NumberColumn(
                    col,
                    format="%.2f%%"
                )
    
    # 显示表格
    st.dataframe(
        data,
        use_container_width=True,
        column_config=column_config
    )
    
    # 添加汇总行
    if currency_columns or percentage_columns:
        st.subheader("汇总统计")
        
        summary_data = {}
        numeric_cols = data.select_dtypes(include=[np.number]).columns
        
        for col in numeric_cols:
            if col in (currency_columns or []):
                summary_data[f"{col}_总计"] = data[col].sum()
                summary_data[f"{col}_平均"] = data[col].mean()
            elif col in (percentage_columns or []):
                summary_data[f"{col}_平均"] = data[col].mean()
                summary_data[f"{col}_中位数"] = data[col].median()
        
        if summary_data:
            summary_df = pd.DataFrame([summary_data])
            st.dataframe(summary_df, use_container_width=True)


def export_table_data(data: pd.DataFrame, filename: str, format_type: str = "csv"):
    """
    导出表格数据
    
    Args:
        data: 数据框
        filename: 文件名
        format_type: 格式类型 (csv, excel, json)
    """
    if format_type == "csv":
        csv_data = data.to_csv(index=False)
        st.download_button(
            label="📥 下载CSV",
            data=csv_data,
            file_name=f"{filename}.csv",
            mime="text/csv"
        )
    
    elif format_type == "excel":
        # 注意：需要安装openpyxl
        try:
            excel_data = data.to_excel(index=False)
            st.download_button(
                label="📥 下载Excel",
                data=excel_data,
                file_name=f"{filename}.xlsx",
                mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            )
        except Exception as e:
            st.error(f"导出Excel失败: {e}")
    
    elif format_type == "json":
        json_data = data.to_json(orient='records', indent=2)
        st.download_button(
            label="📥 下载JSON",
            data=json_data,
            file_name=f"{filename}.json",
            mime="application/json"
        )